package cn.ybk.user.service.impl;

import cn.ybk.basic.constant.RegisterCons;
import cn.ybk.basic.constant.WechatCons;
import cn.ybk.basic.jwt.JwtUtils;
import cn.ybk.basic.jwt.RsaUtils;
import cn.ybk.basic.jwt.UserInfo;
import cn.ybk.basic.util.AjaxResult;
import cn.ybk.basic.util.BusinessException;
import cn.ybk.basic.util.HttpUtil;
import cn.ybk.org.domain.Employee;
import cn.ybk.org.domain.Shop;
import cn.ybk.org.mapper.EmployeeMapper;
import cn.ybk.org.mapper.ShopMapper;
import cn.ybk.system.domain.Menu;
import cn.ybk.system.mapper.MenuMapper;
import cn.ybk.system.mapper.PermissionMapper;
import cn.ybk.user.domain.Logininfo;
import cn.ybk.user.domain.User;
import cn.ybk.user.domain.Wxuser;
import cn.ybk.user.dto.WechatBinderDto;
import cn.ybk.user.dto.WechatDto;
import cn.ybk.user.mapper.LogininfoMapper;
import cn.ybk.user.mapper.UserMapper;
import cn.ybk.user.mapper.WxuserMapper;
import cn.ybk.user.service.LoginService;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.security.PrivateKey;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class LoginServiceImpl implements LoginService {

    @Autowired
    private WxuserMapper wxuserMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ShopMapper shopMapper;
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private EmployeeMapper employeeMapper;

    @Value("${jwt.pri}")
    private String priKey;

    
    // 微信扫码接口
    @Override
    public AjaxResult wechat(WechatDto dto) {
        // 校验数据 notBlank
        // 根据code获取token和openid 请求微信的第二个接口 获取token和openiD
        String url = String.format(WechatCons.SENCOND_TOGET_CODE,
                WechatCons.APPID, WechatCons.SECRET, dto.getCode());
        // 发送请求，接口
        String httpUrl = HttpUtil.httpGet(url);
        if (StringUtils.isBlank(httpUrl)) {
            throw new BusinessException("请求发送错误");
        }
        // json对象转为obj对象
        JSONObject jsonObject = JSONObject.parseObject(httpUrl);
        String accessToken = jsonObject.getString("access_token");
        String openId = jsonObject.getString("openid");
        if (StringUtils.isBlank(accessToken) || StringUtils.isBlank(openId)) {
            throw new BusinessException("accessToken和openId为空");
        }
        // 在wxuser表中根据openid查询是否存在
        Wxuser wxuser = wxuserMapper.findByOpendId(openId);
        if (wxuser == null) {
            // 没有openid 让用户绑定 强制绑定（binder）
            // 拼接URL路径
            StringBuffer sbr = new StringBuffer()
                    .append("?accessToken=")
                    .append(accessToken)
                    .append("&openId=").append(openId);
            // 我们现在返回的是 success:false  msg:nobinder  resultObj:"?accessToken=xxxx&openId=yyy"
            return AjaxResult.me().fail("noBinder").setResultObj(sbr);
        }
        // 有openid 登陆成功
        Logininfo logininfo = logininfoMapper.findByUserId(wxuser.getUserId());
        Map<String, Object> map = getMap(logininfo);
        return AjaxResult.me().success(map);
    }

    // 微信绑定
    @Override
    public AjaxResult wechatBinder(WechatBinderDto dto) {
        // 参数校验 @notblank
        // 校验验证码
        String verifyCode = dto.getVerifyCode();
        String redisPhoneCode = (String) redisTemplate.opsForValue().get(String.format(RegisterCons.BINDER_CODE_KEY, dto.getPhone()));
        if (StringUtils.isBlank(redisPhoneCode) || StringUtils.isBlank(verifyCode) || !redisPhoneCode.equals(verifyCode)) {
            throw new BusinessException("验证码错误");
        }
        // 获取token和openId 调用微信的第三个接口
        String url = String.format(WechatCons.THIRD_TOKEN_OPENDID, dto.getAccessToken(), dto.getOpenId());
        // 发送请求
        String httpUrl = HttpUtil.httpGet(url);
        if (StringUtils.isBlank(httpUrl)) {
            throw new BusinessException("错误情况");
        }
        // 获取 json对象
        JSONObject jsonObject = JSONObject.parseObject(httpUrl);
        // 获取json对象，然后直接转换为wxuser对象（里面的字段要相同）
        Wxuser wxuser = JSONObject.parseObject(httpUrl, Wxuser.class);
        Logininfo logininfo = new Logininfo();
        if (wxuser == null) {
            throw new BusinessException("你没有对象啦");
        }
        // 根据手机号，查询数据库中User表中是否有数据
        User user = userMapper.findByPhone(dto.getPhone());
        if (user == null) {
            System.out.println(user);
            // 没有该用户数据 添加三张表，user wxuser logininfo
            user = dto.getUser();
            BeanUtils.copyProperties(user, logininfo);
            logininfo.setDisable(true);
            logininfo.setType(1);
            logininfoMapper.add(logininfo);
            user.setLogininfoId(logininfo.getId());
            userMapper.add(user);
        } else {
            // 在数据库中根据userid查询logininfo表中的数据
            logininfo = logininfoMapper.findByUserId(user.getId());
        }
        wxuser.setUserId(user.getId());
        wxuserMapper.add(wxuser);
        // 为了返回前端logininfo
        Map<String, Object> map = getMap(logininfo);

        return AjaxResult.me().success(map);
    }


    // 添加数据库
    private Map<String, Object> getMap(Logininfo logininfo) {
        HashMap<String, Object> map = new HashMap<>();
        // 将token和logininfo 返回给前端
        PrivateKey privateKey = RsaUtils.getPrivateKey(JwtUtils.class.getClassLoader().getResource(priKey).getFile());
        UserInfo userInfo = new UserInfo();
        userInfo.setLogininfo(logininfo);
        // 获取jwt的公钥
        if (logininfo.getType() == 0) {
            List<Menu> menus =  menuMapper.findByLogininfo(logininfo.getId());
            userInfo.setMenus(menus);
            List<String> permissions = permissionMapper.findByLogininfo(logininfo.getId());
            userInfo.setPermissions(permissions);
            map.put("menus",menus);
            map.put("permissions",permissions);
            // 根据logininfoid 去查询当前让你的店铺 首先你得是店铺的员工
            Employee emp = employeeMapper.findByLoginfoId(logininfo.getId());
            if (null != emp && null != emp.getShopId()){
                Shop shop =  shopMapper.findById(emp.getShopId());
                userInfo.setShop(shop);
            }
        }
        // 使用公钥 生成token
        String token = JwtUtils.generateTokenExpireInMinutes(userInfo, privateKey, 30000000);
        // 如果是后台登陆 才有 菜单和按钮权限

        logininfo.setEmail(null);
        logininfo.setPassword(null);
        logininfo.setPhone(null);
        map.put("token",token);
        map.put("logininfo", logininfo);
        return map;
    }


}
